#ifndef CUSTOM_REDUCTIONS_HPP
#define CUSTOM_REDUCTIONS_HPP

#include "typeAliases.hpp"
#include "macros.hpp"

namespace hms {

#define OMP_ARRAY_REDUCTION(OPER, OPER_FUNC, ARRAY_TYPE, INIT) \
OMP_PRAGMA(declare reduction(OPER : ARRAY_TYPE : std::transform( \
	omp_out.begin(), omp_out.end(), \
	omp_in.begin(), omp_out.begin(), \
	OPER_FUNC )) \
	initializer( omp_priv = decltype(omp_orig)INIT( omp_orig.size() ) ) )


#define OMP_EIGEN_REDUCTION(OPER, EIGEN_TYPE, INIT) \
OMP_PRAGMA(declare reduction (OPER: EIGEN_TYPE: omp_out=omp_out OPER omp_in) \
     initializer( omp_priv=EIGEN_TYPE::INIT( omp_orig.size() ) ) )

OMP_ARRAY_REDUCTION(+, std::plus<int>(), std::vector<int>, )
OMP_EIGEN_REDUCTION(+, VectorXi, Zero )
OMP_EIGEN_REDUCTION(+, ArrayXi, Zero )
OMP_EIGEN_REDUCTION(+, ArrayXs, Zero )

/*
template<typename Derived>
#pragma omp declare reduction(+ : Eigen::MatrixBase<Derived> : std::transform( \
		omp_out.begin(), omp_out.end(), \
		omp_in.begin(), omp_out.begin(), \
		std::plus<Derived::Scalar>() \
	)) \
	initializer( omp_priv = decltype(omp_orig)::Zero( \
		omp_orig.rows(), omp_orig.cols() \
	) )
*/

}

#endif